package com.zxjbyte.yiyi.framework.mybatis.util;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zxjbyte.yiyi.framework.common.domain.api.OrderBy;
import com.zxjbyte.yiyi.framework.common.domain.api.PageQuery;
import com.zxjbyte.yiyi.framework.common.enums.SortOrder;
import com.zxjbyte.yiyi.framework.common.util.LambdaFieldUtil;
import com.zxjbyte.yiyi.framework.common.util.ServletXUtil;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 分页工具
 * @Author zhangxingjia
 * @Date 2023/3/16 13:40
 * @Version: 1.0
 */
public class Condition {

    /**
     * 获取简单分页
     *
     * @param <T>
     * @return
     */
    public static <T> IPage<T> getSimplePage() {
        int pageNo = Convert.toInt(ServletXUtil.getParameter(PageQuery.PAGE_FIELD_PAGE_NO, PageQuery.DEFAULT_PAGE_NO + ""));
        int pageSize = Convert.toInt(ServletXUtil.getParameter(PageQuery.PAGE_FIELD_PAGE_SIZE, PageQuery.DEFAULT_PAGE_SIZE + ""));
        return new Page<>(pageNo, pageSize);
    }


    /**
     * 获取mybatis plus中的Page
     * @param query
     * @param <T>
     * @return
     */
    public static <T> IPage<T> getPage(PageQuery query) {
        Page<T> page = new Page<>(query.getPageNo(), query.getPageSize());
        if(CollUtil.isNotEmpty(query.getOrders())){
            query.getOrders().forEach(order ->{
                if(SortOrder.ASC == order.getSortOrder()){
                    page.addOrder(OrderItem.asc(StrUtil.trim(order.getField())));
                }else {
                    page.addOrder(OrderItem.desc(StrUtil.trim(order.getField())));
                }
            });
        }
        return page;
    }

    public static <T> IPage<T> getPage(PageQuery query, LinkedHashMap<Function<T, ?>, SortOrder> sortingFields) {
        return getPage(buildOrder(query, sortingFields));
    }

    public static <T> IPage<T> getPage(PageQuery query, Function<T, ?> k1, SortOrder v1) {
        return getPage(query, fromEntries(entryOf(k1, v1)));
    }

    public static <T> IPage<T> getPage(PageQuery query, Function<T, ?> k1, SortOrder v1, Function<T, ?> k2, SortOrder v2) {
        return getPage(query, fromEntries(entryOf(k1, v1), entryOf(k2, v2)));
    }

    public static <T> IPage<T> getPage(PageQuery query, Function<T, ?> k1, SortOrder v1, Function<T, ?> k2, SortOrder v2, Function<T, ?> k3, SortOrder v3) {
        return getPage(query, fromEntries(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3)));
    }

    public static <T> IPage<T> getPage(PageQuery query, Function<T, ?> k1, SortOrder v1, Function<T, ?> k2, SortOrder v2, Function<T, ?> k3, SortOrder v3, Function<T, ?> k4, SortOrder v4) {
        return getPage(query, fromEntries(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4)));
    }

    public static <T> IPage<T> getPage(PageQuery query, Function<T, ?> k1, SortOrder v1, Function<T, ?> k2, SortOrder v2, Function<T, ?> k3, SortOrder v3, Function<T, ?> k4, SortOrder v4, Function<T, ?> k5, SortOrder v5) {
        return getPage(query, fromEntries(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4), entryOf(k5, v5)));
    }

    private static <T> Map.Entry<Function<T, ?>, SortOrder> entryOf(Function<T, ?> key, SortOrder value){
        return new AbstractMap.SimpleEntry<>(key, value);
    }

    private static <T> LinkedHashMap<Function<T, ?>, SortOrder> fromEntries(Map.Entry<Function<T, ?>, SortOrder> ... entries){
        if(Objects.nonNull(entries) && entries.length > 0){
            LinkedHashMap<Function<T, ?>, SortOrder> linkedHashMap = Arrays.stream(entries)
                    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (v1, v2) -> v1, // merge function
                            LinkedHashMap::new)); // map supplier
            return linkedHashMap;
        }
        return null;
    }

    /**
     * 构建排序参数
     * @param query
     * @param sortingFields
     */
    public static <T> PageQuery buildOrder(PageQuery query, LinkedHashMap<Function<T, ?>, SortOrder> sortingFields){
        if(CollUtil.isEmpty(sortingFields)){
            return query;
        }
        query.setOrders(sortingFields.entrySet().stream()
                .map(entry -> new OrderBy(StrUtil.toUnderlineCase(LambdaFieldUtil.getFieldName(entry.getKey())), entry.getValue()))
                .collect(Collectors.toList()));
        return query;
    }


}
